import * as fs from 'fs/promises';
import * as path from 'path';
import { LogRotationInfo, LogConfig } from '../types';
import { LogFormatter } from '../utils/logFormatter';

export class LogRotationService {
  private rotationInfo: LogRotationInfo | null = null;
  private rotationTimer: NodeJS.Timeout | null = null;
  private isRotating = false;
  private logDirectory: string;
  private config: LogConfig;

  constructor(config: LogConfig) {
    this.config = config;
    this.logDirectory = path.resolve(config.directory);
  }

  /**
   * 初始化日志轮转服务
   */
  async initialize(): Promise<void> {
    try {
      // 确保日志目录存在
      await this.ensureLogDirectory();
      
      // 初始化当前日志文件
      await this.initializeCurrentLogFile();
      
      // 启动轮转定时器
      this.startRotationTimer();
      
      console.log(`日志轮转服务已启动，当前日志文件: ${this.rotationInfo?.currentFile}`);
    } catch (error) {
      console.error('日志轮转服务初始化失败:', error);
      throw error;
    }
  }

  /**
   * 停止日志轮转服务
   */
  async stop(): Promise<void> {
    // 停止定时器
    if (this.rotationTimer) {
      clearInterval(this.rotationTimer);
      this.rotationTimer = null;
    }

    // 关闭当前文件句柄
    if (this.rotationInfo?.fileHandle) {
      try {
        await this.rotationInfo.fileHandle.close();
      } catch (error) {
        console.warn('关闭日志文件句柄失败:', error);
      }
    }

    this.rotationInfo = null;
    console.log('日志轮转服务已停止');
  }

  /**
   * 获取当前日志文件路径
   */
  getCurrentLogFile(): string | null {
    return this.rotationInfo?.currentFile || null;
  }

  /**
   * 获取当前文件句柄
   */
  getCurrentFileHandle(): any {
    return this.rotationInfo?.fileHandle;
  }

  /**
   * 手动触发日志轮转
   */
  async forceRotation(): Promise<void> {
    if (this.isRotating) {
      console.warn('日志轮转正在进行中，跳过本次请求');
      return;
    }

    await this.performRotation();
  }

  /**
   * 检查是否需要轮转
   */
  needsRotation(): boolean {
    if (!this.rotationInfo) {
      return true;
    }

    const now = new Date();
    return now >= this.rotationInfo.nextRotationTime;
  }

  /**
   * 确保日志目录存在
   */
  private async ensureLogDirectory(): Promise<void> {
    try {
      await fs.access(this.logDirectory);
    } catch {
      // 目录不存在，创建它
      await fs.mkdir(this.logDirectory, { recursive: true });
      console.log(`创建日志目录: ${this.logDirectory}`);
    }
  }

  /**
   * 初始化当前日志文件
   */
  private async initializeCurrentLogFile(): Promise<void> {
    const now = new Date();
    const fileName = LogFormatter.generateLogFileName(now);
    const filePath = path.join(this.logDirectory, fileName);

    // 检查文件是否已存在
    let fileExists = false;
    try {
      await fs.access(filePath);
      fileExists = true;
    } catch {
      fileExists = false;
    }

    // 打开文件句柄（追加模式）
    const fileHandle = await fs.open(filePath, 'a');

    // 如果是新文件，写入文件头信息
    if (!fileExists) {
      const header = this.generateLogFileHeader();
      await fileHandle.write(header);
    }

    // 更新轮转信息
    this.rotationInfo = {
      currentFile: filePath,
      nextRotationTime: this.calculateNextRotationTime(now),
      fileHandle
    };
  }

  /**
   * 计算下次轮转时间
   */
  private calculateNextRotationTime(current: Date): Date {
    const next = new Date(current);
    
    if (this.config.rotation === 'hourly') {
      // 下一个整点
      next.setHours(next.getHours() + 1);
      next.setMinutes(0);
      next.setSeconds(0);
      next.setMilliseconds(0);
    } else {
      // 第二天凌晨
      next.setDate(next.getDate() + 1);
      next.setHours(0);
      next.setMinutes(0);
      next.setSeconds(0);
      next.setMilliseconds(0);
    }
    
    return next;
  }

  /**
   * 启动轮转定时器
   */
  private startRotationTimer(): void {
    // 每分钟检查一次是否需要轮转
    this.rotationTimer = setInterval(async () => {
      if (this.needsRotation()) {
        await this.performRotation();
      }
    }, 60 * 1000); // 60秒
  }

  /**
   * 执行日志轮转
   */
  private async performRotation(): Promise<void> {
    if (this.isRotating) {
      return;
    }

    this.isRotating = true;

    try {
      console.log('开始执行日志轮转...');

      // 关闭当前文件句柄
      if (this.rotationInfo?.fileHandle) {
        await this.rotationInfo.fileHandle.close();
      }

      // 创建新的日志文件
      await this.initializeCurrentLogFile();

      console.log(`日志轮转完成，新文件: ${this.rotationInfo?.currentFile}`);
    } catch (error) {
      console.error('日志轮转失败:', error);
      // 轮转失败时尝试恢复
      await this.recoverFromRotationFailure();
    } finally {
      this.isRotating = false;
    }
  }

  /**
   * 从轮转失败中恢复
   */
  private async recoverFromRotationFailure(): Promise<void> {
    try {
      // 如果当前没有可用的文件句柄，尝试重新创建
      if (!this.rotationInfo?.fileHandle) {
        await this.initializeCurrentLogFile();
      }
    } catch (error) {
      console.error('日志轮转恢复失败:', error);
      // 完全失败，清理状态
      this.rotationInfo = null;
    }
  }

  /**
   * 生成日志文件头信息
   */
  private generateLogFileHeader(): string {
    const timestamp = new Date().toISOString();
    const header = [
      `# CLI TUI Application Log File`,
      `# Created: ${timestamp}`,
      `# Format: [Timestamp] [Level] [Source] Message`,
      `# Rotation: ${this.config.rotation}`,
      `# Level: ${this.config.level}`,
      ``,
      ``
    ].join('\n');

    return header;
  }

  /**
   * 检查文件大小是否超过限制
   */
  async checkFileSize(): Promise<boolean> {
    if (!this.rotationInfo?.currentFile) {
      return false;
    }

    try {
      const stats = await fs.stat(this.rotationInfo.currentFile);
      const maxSizeBytes = this.config.maxFileSize * 1024 * 1024; // 转换为字节
      return stats.size >= maxSizeBytes;
    } catch (error) {
      console.warn('检查文件大小失败:', error);
      return false;
    }
  }

  /**
   * 获取日志目录中的所有日志文件
   */
  async getLogFiles(): Promise<string[]> {
    try {
      const files = await fs.readdir(this.logDirectory);
      return files
        .filter(file => file.match(/^cli-\d{4}-\d{2}-\d{2}-\d{2}\.log$/))
        .map(file => path.join(this.logDirectory, file))
        .sort(); // 按文件名排序
    } catch (error) {
      console.error('获取日志文件列表失败:', error);
      return [];
    }
  }

  /**
   * 验证当前日志文件状态
   */
  async validateCurrentLogFile(): Promise<boolean> {
    if (!this.rotationInfo?.currentFile) {
      return false;
    }

    try {
      // 检查文件是否存在
      await fs.access(this.rotationInfo.currentFile);
      
      // 检查文件句柄是否有效
      if (!this.rotationInfo.fileHandle) {
        return false;
      }

      return true;
    } catch {
      return false;
    }
  }

  /**
   * 获取轮转统计信息
   */
  getRotationStats(): {
    currentFile: string | null;
    nextRotationTime: Date | null;
    isRotating: boolean;
    rotationInterval: string;
  } {
    return {
      currentFile: this.rotationInfo?.currentFile || null,
      nextRotationTime: this.rotationInfo?.nextRotationTime || null,
      isRotating: this.isRotating,
      rotationInterval: this.config.rotation
    };
  }
}